package com.lifeverse.service;

import com.lifeverse.dto.LifeEntityGroupCreateDTO;
import com.lifeverse.dto.LifeEntityGroupDTO;
import com.lifeverse.entity.LifeEntity;
import com.lifeverse.entity.LifeEntityGroup;
import com.lifeverse.exception.BusinessException;
import com.lifeverse.repository.LifeEntityGroupRepository;
import com.lifeverse.repository.LifeEntityRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 群体管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GroupService {
    
    private final LifeEntityGroupRepository groupRepository;
    private final LifeEntityRepository lifeEntityRepository;
    
    /**
     * 创建群体
     */
    @Transactional
    public LifeEntityGroupDTO createGroup(LifeEntityGroupCreateDTO createDTO) {
        log.info("创建群体: name={}, type={}", createDTO.getGroupName(), createDTO.getGroupType());
        
        // 检查群体名称是否已存在
        if (groupRepository.findByGroupName(createDTO.getGroupName()).isPresent()) {
            throw new BusinessException("群体名称已存在: " + createDTO.getGroupName());
        }
        
        // 创建群体实体
        LifeEntityGroup group = new LifeEntityGroup();
        group.setGroupName(createDTO.getGroupName());
        group.setGroupType(createDTO.getGroupType());
        group.setGroupStatus(LifeEntityGroup.GroupStatus.FORMING);
        group.setDescription(createDTO.getDescription());
        group.setObjectives(createDTO.getObjectives());
        group.setRules(createDTO.getRules());
        group.setCulture(createDTO.getCulture());
        group.setTags(createDTO.getTags());
        group.setAttributes(createDTO.getAttributes());
        group.setIsPublic(createDTO.getIsPublic());
        group.setAllowFreeJoin(createDTO.getAllowFreeJoin());
        group.setMaxMembers(createDTO.getMaxMembers());
        group.setMinMembers(createDTO.getMinMembers());
        group.setFormedAt(LocalDateTime.now());
        group.setLastActivityAt(LocalDateTime.now());
        
        // 设置领导者
        if (createDTO.getLeaderId() != null) {
            LifeEntity leader = lifeEntityRepository.findById(createDTO.getLeaderId())
                    .orElseThrow(() -> new BusinessException("领导者不存在: " + createDTO.getLeaderId()));
            group.setLeader(leader);
        }
        
        // 添加初始成员
        Set<LifeEntity> members = new HashSet<>();
        if (createDTO.getMemberIds() != null && !createDTO.getMemberIds().isEmpty()) {
            for (Long memberId : createDTO.getMemberIds()) {
                LifeEntity member = lifeEntityRepository.findById(memberId)
                        .orElseThrow(() -> new BusinessException("成员不存在: " + memberId));
                members.add(member);
            }
        }
        
        // 如果有领导者且不在成员列表中，自动添加
        if (group.getLeader() != null) {
            members.add(group.getLeader());
        }
        
        group.setMembers(members);
        group.setMemberCount(members.size());
        
        // 如果成员数量达到最小要求，激活群体
        if (group.getMemberCount() >= group.getMinMembers()) {
            group.setGroupStatus(LifeEntityGroup.GroupStatus.ACTIVE);
        }
        
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功创建群体: id={}, memberCount={}", savedGroup.getId(), savedGroup.getMemberCount());
        return convertToDTO(savedGroup);
    }
    
    /**
     * 添加成员到群体
     */
    @Transactional
    public LifeEntityGroupDTO addMember(Long groupId, Long memberId) {
        log.info("添加成员到群体: groupId={}, memberId={}", groupId, memberId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        LifeEntity member = lifeEntityRepository.findById(memberId)
                .orElseThrow(() -> new BusinessException("生命体不存在: " + memberId));
        
        // 检查是否可以添加新成员
        if (!group.canAddMember()) {
            throw new BusinessException("群体无法添加新成员");
        }
        
        // 检查成员是否已在群体中
        if (group.getMembers().contains(member)) {
            throw new BusinessException("成员已在群体中");
        }
        
        group.addMember(member);
        
        // 如果群体状态为组建中且成员数量达到最小要求，激活群体
        if (group.getGroupStatus() == LifeEntityGroup.GroupStatus.FORMING 
            && group.getMemberCount() >= group.getMinMembers()) {
            group.activate();
        }
        
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功添加成员: groupId={}, memberId={}, newMemberCount={}", 
                groupId, memberId, savedGroup.getMemberCount());
        return convertToDTO(savedGroup);
    }
    
    /**
     * 从群体移除成员
     */
    @Transactional
    public LifeEntityGroupDTO removeMember(Long groupId, Long memberId) {
        log.info("从群体移除成员: groupId={}, memberId={}", groupId, memberId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        LifeEntity member = lifeEntityRepository.findById(memberId)
                .orElseThrow(() -> new BusinessException("生命体不存在: " + memberId));
        
        // 检查成员是否在群体中
        if (!group.getMembers().contains(member)) {
            throw new BusinessException("成员不在群体中");
        }
        
        group.removeMember(member);
        
        // 如果移除的是领导者，清空领导者
        if (group.getLeader() != null && group.getLeader().equals(member)) {
            group.setLeader(null);
        }
        
        // 如果成员数量不足最小要求，将群体状态改为组建中
        if (group.getMemberCount() < group.getMinMembers()) {
            group.setGroupStatus(LifeEntityGroup.GroupStatus.FORMING);
        }
        
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功移除成员: groupId={}, memberId={}, newMemberCount={}", 
                groupId, memberId, savedGroup.getMemberCount());
        return convertToDTO(savedGroup);
    }
    
    /**
     * 设置群体领导者
     */
    @Transactional
    public LifeEntityGroupDTO setLeader(Long groupId, Long leaderId) {
        log.info("设置群体领导者: groupId={}, leaderId={}", groupId, leaderId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        LifeEntity leader = lifeEntityRepository.findById(leaderId)
                .orElseThrow(() -> new BusinessException("生命体不存在: " + leaderId));
        
        // 检查领导者是否在群体中
        if (!group.getMembers().contains(leader)) {
            throw new BusinessException("领导者必须是群体成员");
        }
        
        group.setLeader(leader);
        group.updateLastActivityTime();
        
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功设置群体领导者: groupId={}, leaderId={}", groupId, leaderId);
        return convertToDTO(savedGroup);
    }
    
    /**
     * 激活群体
     */
    @Transactional
    public LifeEntityGroupDTO activateGroup(Long groupId) {
        log.info("激活群体: groupId={}", groupId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        if (!group.hasSufficientMembers()) {
            throw new BusinessException("群体成员数量不足，无法激活");
        }
        
        group.activate();
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功激活群体: groupId={}", groupId);
        return convertToDTO(savedGroup);
    }
    
    /**
     * 休眠群体
     */
    @Transactional
    public LifeEntityGroupDTO dormantGroup(Long groupId) {
        log.info("休眠群体: groupId={}", groupId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        group.dormant();
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功休眠群体: groupId={}", groupId);
        return convertToDTO(savedGroup);
    }
    
    /**
     * 解散群体
     */
    @Transactional
    public LifeEntityGroupDTO dissolveGroup(Long groupId) {
        log.info("解散群体: groupId={}", groupId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        group.dissolve();
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功解散群体: groupId={}", groupId);
        return convertToDTO(savedGroup);
    }
    
    /**
     * 根据ID查询群体
     */
    public LifeEntityGroupDTO getGroupById(Long groupId) {
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        return convertToDTO(group);
    }
    
    /**
     * 查询所有活跃群体
     */
    public List<LifeEntityGroupDTO> getActiveGroups() {
        List<LifeEntityGroup> groups = groupRepository.findActiveGroups();
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据类型查询群体
     */
    public List<LifeEntityGroupDTO> getGroupsByType(LifeEntityGroup.GroupType type) {
        List<LifeEntityGroup> groups = groupRepository.findByGroupType(type);
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查询生命体所属的群体
     */
    public List<LifeEntityGroupDTO> getGroupsByMember(Long memberId) {
        LifeEntity member = lifeEntityRepository.findById(memberId)
                .orElseThrow(() -> new BusinessException("生命体不存在: " + memberId));
        
        List<LifeEntityGroup> groups = groupRepository.findGroupsByMember(member);
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查询高智慧群体
     */
    public List<LifeEntityGroupDTO> getHighWisdomGroups() {
        List<LifeEntityGroup> groups = groupRepository.findHighWisdomGroups();
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查询健康群体
     */
    public List<LifeEntityGroupDTO> getHealthyGroups() {
        List<LifeEntityGroup> groups = groupRepository.findHealthyGroups();
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查询需要关注的群体
     */
    public List<LifeEntityGroupDTO> getGroupsNeedingAttention() {
        List<LifeEntityGroup> groups = groupRepository.findGroupsNeedingAttention();
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 查询可以加入新成员的群体
     */
    public List<LifeEntityGroupDTO> getGroupsAcceptingNewMembers() {
        List<LifeEntityGroup> groups = groupRepository.findGroupsAcceptingNewMembers();
        return groups.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 分页查询群体
     */
    public Page<LifeEntityGroupDTO> getGroupsByStatus(LifeEntityGroup.GroupStatus status, Pageable pageable) {
        Page<LifeEntityGroup> groupPage = groupRepository.findByGroupStatus(status, pageable);
        
        List<LifeEntityGroupDTO> dtoList = groupPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(dtoList, pageable, groupPage.getTotalElements());
    }
    
    /**
     * 更新群体评分
     */
    @Transactional
    public LifeEntityGroupDTO updateGroupScores(Long groupId, Map<String, BigDecimal> scores) {
        log.info("更新群体评分: groupId={}", groupId);
        
        LifeEntityGroup group = groupRepository.findById(groupId)
                .orElseThrow(() -> new BusinessException("群体不存在: " + groupId));
        
        // 更新各项评分
        if (scores.containsKey("wisdomScore")) {
            group.setWisdomScore(scores.get("wisdomScore"));
        }
        if (scores.containsKey("cohesionScore")) {
            group.setCohesionScore(scores.get("cohesionScore"));
        }
        if (scores.containsKey("efficiencyScore")) {
            group.setEfficiencyScore(scores.get("efficiencyScore"));
        }
        if (scores.containsKey("innovationScore")) {
            group.setInnovationScore(scores.get("innovationScore"));
        }
        if (scores.containsKey("collaborationScore")) {
            group.setCollaborationScore(scores.get("collaborationScore"));
        }
        if (scores.containsKey("learningScore")) {
            group.setLearningScore(scores.get("learningScore"));
        }
        if (scores.containsKey("adaptabilityScore")) {
            group.setAdaptabilityScore(scores.get("adaptabilityScore"));
        }
        if (scores.containsKey("stabilityScore")) {
            group.setStabilityScore(scores.get("stabilityScore"));
        }
        if (scores.containsKey("diversityIndex")) {
            group.setDiversityIndex(scores.get("diversityIndex"));
        }
        if (scores.containsKey("activityLevel")) {
            group.setActivityLevel(scores.get("activityLevel"));
        }
        
        group.updateLastActivityTime();
        LifeEntityGroup savedGroup = groupRepository.save(group);
        
        log.info("成功更新群体评分: groupId={}", groupId);
        return convertToDTO(savedGroup);
    }
    
    /**
     * 计算群体统计信息
     */
    public Map<String, Object> calculateGroupStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 按类型统计
        List<Object[]> typeStats = groupRepository.countGroupsByType();
        Map<String, Long> typeCount = new HashMap<>();
        for (Object[] stat : typeStats) {
            typeCount.put(stat[0].toString(), (Long) stat[1]);
        }
        statistics.put("typeCount", typeCount);
        
        // 按状态统计
        List<Object[]> statusStats = groupRepository.countGroupsByStatus();
        Map<String, Long> statusCount = new HashMap<>();
        for (Object[] stat : statusStats) {
            statusCount.put(stat[0].toString(), (Long) stat[1]);
        }
        statistics.put("statusCount", statusCount);
        
        // 平均群体大小
        Double avgSize = groupRepository.calculateAverageGroupSize();
        statistics.put("averageGroupSize", avgSize != null ? avgSize : 0.0);
        
        // 平均智慧评分
        BigDecimal avgWisdom = groupRepository.calculateAverageWisdomScore();
        statistics.put("averageWisdomScore", avgWisdom != null ? avgWisdom : BigDecimal.ZERO);
        
        return statistics;
    }
    
    /**
     * 转换为DTO
     */
    private LifeEntityGroupDTO convertToDTO(LifeEntityGroup group) {
        LifeEntityGroupDTO dto = new LifeEntityGroupDTO();
        BeanUtils.copyProperties(group, dto);
        
        // 设置成员信息
        if (group.getMembers() != null) {
            dto.setMemberIds(group.getMembers().stream()
                    .map(LifeEntity::getId)
                    .collect(Collectors.toList()));
            dto.setMemberNames(group.getMembers().stream()
                    .map(LifeEntity::getName)
                    .collect(Collectors.toList()));
        }
        
        // 设置领导者信息
        if (group.getLeader() != null) {
            dto.setLeaderId(group.getLeader().getId());
            dto.setLeaderName(group.getLeader().getName());
        }
        
        // 设置计算字段
        dto.setOverallScore(group.calculateOverallScore());
        dto.setExistenceDays(group.getExistenceDays());
        dto.setIsHealthy(group.isHealthy());
        dto.setIsStable(group.isStable());
        dto.setIsEfficient(group.isEfficient());
        dto.setIsInnovative(group.isInnovative());
        dto.setCanAddMember(group.canAddMember());
        dto.setHasSufficientMembers(group.hasSufficientMembers());
        
        return dto;
    }
}